package stage;

import java.io.*;
import java.util.*;

import repository.Repository;
import fileoperation.*;
import gitobject.*;

public class Index {
    public static LinkedList<String[]> indexFileList = new LinkedList<>();
    private static String path = Repository.getGitDir();
    private volatile static Index index;
    /**
     * Constructor
     * @throws IOException
     */
    private Index() throws IOException {
        if(!new File(path+File.separator+"index").exists()){
            FileCreation.createFile(path,"index","");
        }
        else{
            indexFileList = LoadIndex();
        }
    }
    public static Index getInstance() throws IOException {
        if(index == null ){
            synchronized (Index.class){
                if(index == null ){
                    index = new Index();
                }
            }
        }
        return index;
    }

    /**
     *  Load index to .jit/index
     * @return LinedList<String[]> stringList
     * @throws IOException
     */
    public static LinkedList<String[]> LoadIndex() throws IOException {
        if (new File(path + File.separator + "index").exists()) {
            File indexFile = new File(path + File.separator + "index");
            FileInputStream is = new FileInputStream(indexFile);
            BufferedReader br=new BufferedReader(new InputStreamReader(is));
            LinkedList<String[]> stringList =  new LinkedList<>();
            try{
                String line=br.readLine();
                while (line!=null){
                    String[] tmp = line.split(" ");
                    stringList.add(tmp);
                    line=br.readLine();
                }

            }catch (IOException e){
                e.printStackTrace();
            }finally {
                try {
                    br.close();
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return stringList;
        } else {
            throw new IOException("Index file doesn't exist.");
        }
    }

    /**
     * Get file's index in indexFileList, if there is no such file in the index, return -1
     * @param file
     * @return index
     * @throws IOException
     */
    public int getFileIndex(File file) throws IOException {
        String workDir = Repository.getWorkTree();
        String fileName = file.getPath().substring(workDir.length() + 1);
        //String fileName = file.getPath();
        for(int i = 0; i < indexFileList.size(); i++){
            //suppose indexFileList.get(i) = {"type","hash","filename","timestamp"}
            if(indexFileList.get(i)[2].equals(fileName)) return i;
        }
        return -1;
    }

    /**
     * Remove certain file from indexFileList
     * @param file
     * @throws IOException
     */
    public void removeIndex(File file) throws IOException {
        int idx = getFileIndex(file);
        if(idx != -1) indexFileList.remove(idx);
        writeIndex();
    }

    /**
     * Save index to .jit/index
     * @throws IOException
     */
    public void writeIndex() throws IOException {
        if(new File(path + File.separator + "index").exists()) {
            File indexFile = new File(path + File.separator + "index");
            FileWriter fw = new FileWriter(indexFile);
            for(String[] tmp : indexFileList) {
                String str = arrayToString(tmp);
                fw.write(str);
                fw.write("\n");
            }
            fw.flush();
            fw.close();
        }
    }

    /**
     * Insert a record into indexFileList
     * @param file
     * @throws Exception
     */
    public void insertIndex(File file) throws Exception {
        try{
            //Generate a new record
            String[] record = new String[4];
            Blob blob = new Blob(file);
            String workDir = Repository.getWorkTree();
            String fileName = file.getPath().substring(workDir.length() + 1);

            long time = file.lastModified();
            String timeStamp = String.valueOf(time);

            record[0] = "100644";
            record[1] = blob.getKey();
            record[2] = fileName;
            record[3] = timeStamp;
            indexFileList.add(record);
            //save indexFileList to .jit/index
            writeIndex();
            //Save file(blob object) into local repo.
            blob.writeObject();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * turn array to string
     * @param arr
     * @return
     */
    public static String arrayToString(String[] arr) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            sb.append(arr[i] + " ");
        }
        String res = sb.toString().substring(0, sb.length() - 1);
        return res;
    }

    /**
     * get hashmap of index
     * @return
     * @throws IOException
     */
    public static HashMap<String, String> getIndexMap() throws IOException {
        HashMap<String, String> indexFiles = new HashMap<>();
        for(String[] indexItem: Index.getInstance().indexFileList){
            indexFiles.put(indexItem[1], indexItem[2]);//hash,FilePath
        }
        return indexFiles;
    }


    /**
     * return indexFileList
     */
    public LinkedList<String[]> getIndexFileList() {
        return indexFileList;
    }

}


